//
// Created by LONG on 2020/10/18.
//

#include "cellFsm.h"
#include "../../../../../ccore/misc/include/misc.h"

void RAN_L3_CELL_SMH_Default(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    result->procRslt = O5G_RC_OK;
}

void RAN_L3_CELL_SMH_ProcCellSetupTrigger(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_RanL3CellInst *pCellInst;
    S_RanL1ApiMsgParamsReq paramsReq;

    pCellInst = evtCtxt->context;

    paramsReq.commMsgHdr.type = RAN_L1_API_MSG_PARAMS_REQ;
    paramsReq.commMsgHdr.size = sizeof(paramsReq);
    paramsReq.nbIdx = pCellInst->nbIdx;
    paramsReq.cellIdx = pCellInst->cellIdx;
    send(gpRanL3Context->l2SockFd, &paramsReq, sizeof(paramsReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = RAN_L3_CELL_SM_EVENT_RECV_L1_PARAMS_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void RAN_L3_CELL_SMH_ProcL1ParamsRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_RanL3CellInst *pCellInst;
    S_RanL1ApiMsgConfigReq configReq;

    pCellInst = evtCtxt->context;

    configReq.commMsgHdr.type = RAN_L1_API_MSG_CONFIG_REQ;
    configReq.commMsgHdr.size = sizeof(configReq);
    configReq.nbIdx = pCellInst->nbIdx;
    configReq.cellIdx = pCellInst->cellIdx;
    send(gpRanL3Context->l2SockFd, &configReq, sizeof(configReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = RAN_L3_CELL_SM_EVENT_RECV_L1_CONFIG_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void RAN_L3_CELL_SMH_ProcL1ConfigRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_RanL3CellInst *pCellInst;
    S_RanL3L2MsgConfigReq configReq;

    pCellInst = evtCtxt->context;

    configReq.commMsgHdr.type = RAN_L3_L2_MSG_CONFIG_REQ;
    configReq.commMsgHdr.size = sizeof(configReq);
    configReq.nbIdx = pCellInst->nbIdx;
    configReq.cellIdx = pCellInst->cellIdx;
    send(gpRanL3Context->l2SockFd, &configReq, sizeof(configReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = RAN_L3_CELL_SM_EVENT_RECV_L2_CONFIG_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void RAN_L3_CELL_SMH_ProcL2ConfigRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_RanL3CellInst *pCellInst;
    S_RanL1ApiMsgStartReq startReq;

    pCellInst = evtCtxt->context;

    startReq.commMsgHdr.type = RAN_L1_API_MSG_START_REQ;
    startReq.commMsgHdr.size = sizeof(startReq);
    startReq.nbIdx = pCellInst->nbIdx;
    startReq.cellIdx = pCellInst->cellIdx;
    send(gpRanL3Context->l2SockFd, &startReq, sizeof(startReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = RAN_L3_CELL_SM_EVENT_RECV_L1_START_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void RAN_L3_CELL_SMH_ProcL1StartRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_RanL3CellInst *pCellInst;
    S_RanL3L2MsgStartReq startReq;

    pCellInst = evtCtxt->context;

    startReq.commMsgHdr.type = RAN_L3_L2_MSG_START_REQ;
    startReq.commMsgHdr.size = sizeof(startReq);
    startReq.nbIdx = pCellInst->nbIdx;
    startReq.cellIdx = pCellInst->cellIdx;
    send(gpRanL3Context->l2SockFd, &startReq, sizeof(startReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = RAN_L3_CELL_SM_EVENT_RECV_L2_START_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void RAN_L3_CELL_SMH_ProcL2StartRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    S_RanL3CellInst *pCellInst;
    S_RanL3L2MsgMibTxReq mibTxReq;

    pCellInst = evtCtxt->context;

    mibTxReq.commMsgHdr.type = RAN_L3_L2_MSG_MIB_TX_REQ;
    mibTxReq.commMsgHdr.size = sizeof(mibTxReq);
    mibTxReq.nbIdx = pCellInst->nbIdx;
    mibTxReq.cellIdx = pCellInst->cellIdx;
    memcpy(mibTxReq.mib, pCellInst->mibBuffer, pCellInst->mibSize);
    mibTxReq.mibSize = pCellInst->mibSize;
    send(gpRanL3Context->l2SockFd, &mibTxReq, sizeof(mibTxReq), MSG_DONTWAIT);

//    result->newEventInd = 1;
//    result->newEvent = RAN_L3_CELL_SM_EVENT_RECV_L2_MIB_TX_RSP;
//    result->newContext = evtCtxt->context;
    result->procRslt = O5G_RC_OK;
}

void RAN_L3_CELL_SMH_ProcL2MibTxRsp(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result)
{
    RAN_ADD_DBG_CODE(RAN_DC_L3_CELL_SETUP_SUCC);
    result->procRslt = O5G_RC_OK;
}

FSM_DEF_BEG(RAN_L3_CELL_FSM, RAN_L3_CELL_SM_STATE_INIT)

    FSM_STATE_DEF_BEG(RAN_L3_CELL_SM_STATE_INIT)
        FSM_EVENT_HANDLE_DEF(RAN_L3_CELL_SM_EVENT_CELL_SETUP_TRIGGER, RAN_L3_CELL_SMH_ProcCellSetupTrigger)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_WAIT_L1_PARAMS_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(RAN_L3_CELL_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
    FSM_STATE_DEF_END(RAN_L3_CELL_SM_STATE_INIT)

    FSM_STATE_DEF_BEG(RAN_L3_CELL_SM_STATE_WAIT_L1_PARAMS_RSP)
        FSM_EVENT_HANDLE_DEF(RAN_L3_CELL_SM_EVENT_RECV_L1_PARAMS_RSP, RAN_L3_CELL_SMH_ProcL1ParamsRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_WAIT_L1_CONFIG_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(RAN_L3_CELL_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
    FSM_STATE_DEF_END(RAN_L3_CELL_SM_STATE_WAIT_L1_PARAMS_RSP)

    FSM_STATE_DEF_BEG(RAN_L3_CELL_SM_STATE_WAIT_L1_CONFIG_RSP)
        FSM_EVENT_HANDLE_DEF(RAN_L3_CELL_SM_EVENT_RECV_L1_CONFIG_RSP, RAN_L3_CELL_SMH_ProcL1ConfigRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_WAIT_L2_CONFIG_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(RAN_L3_CELL_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
    FSM_STATE_DEF_END(RAN_L3_CELL_SM_STATE_WAIT_L1_CONFIG_RSP)

    FSM_STATE_DEF_BEG(RAN_L3_CELL_SM_STATE_WAIT_L2_CONFIG_RSP)
        FSM_EVENT_HANDLE_DEF(RAN_L3_CELL_SM_EVENT_RECV_L2_CONFIG_RSP, RAN_L3_CELL_SMH_ProcL2ConfigRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_WAIT_L1_START_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(RAN_L3_CELL_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
    FSM_STATE_DEF_END(RAN_L3_CELL_SM_STATE_WAIT_L2_CONFIG_RSP)

    FSM_STATE_DEF_BEG(RAN_L3_CELL_SM_STATE_WAIT_L1_START_RSP)
        FSM_EVENT_HANDLE_DEF(RAN_L3_CELL_SM_EVENT_RECV_L1_START_RSP, RAN_L3_CELL_SMH_ProcL1StartRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_WAIT_L2_START_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(RAN_L3_CELL_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
    FSM_STATE_DEF_END(RAN_L3_CELL_SM_STATE_WAIT_L1_START_RSP)

    FSM_STATE_DEF_BEG(RAN_L3_CELL_SM_STATE_WAIT_L2_START_RSP)
        FSM_EVENT_HANDLE_DEF(RAN_L3_CELL_SM_EVENT_RECV_L2_START_RSP, RAN_L3_CELL_SMH_ProcL2StartRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_WAIT_L2_MIB_TX_RSP)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(RAN_L3_CELL_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
    FSM_STATE_DEF_END(RAN_L3_CELL_SM_STATE_WAIT_L2_START_RSP)

    FSM_STATE_DEF_BEG(RAN_L3_CELL_SM_STATE_WAIT_L2_MIB_TX_RSP)
        FSM_EVENT_HANDLE_DEF(RAN_L3_CELL_SM_EVENT_RECV_L2_MIB_TX_RSP, RAN_L3_CELL_SMH_ProcL2MibTxRsp)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_CELL_SETUP_SUCC)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
        FSM_DEFAULT_EVENT_HANDLE_DEF(RAN_L3_CELL_SMH_Default)
            FSM_STATE_TRANS_DEF(O5G_RC_OK, RAN_L3_CELL_SM_STATE_INIT)
            FSM_STATE_TRANS_DEF(O5G_RC_ER, RAN_L3_CELL_SM_STATE_INIT)
    FSM_STATE_DEF_END(RAN_L3_CELL_SM_STATE_WAIT_L2_MIB_TX_RSP)

FSM_DEF_END(RAN_L3_CELL_FSM)

int32_t RAN_L3_CELL_SM_Init(void)
{
    uint32_t nbLoop;
    uint32_t cellLoop;
    S_RanL3NbInst *pNbInst;
    S_RanL3CellInst *pCellInst;
    char fsmInstId[64];

    gpRanL3Context->cellFsm = FSM_INIT(RAN_L3_CELL_FSM);
    IF_RETURN(==, NULL, gpRanL3Context->cellFsm, O5G_RC_ER, "RAN_L3_CELL_SM_Init() FSM_INIT(RAN_L3_CELL_FSM) error!\n");

    FSM_SetLogCallback(gpRanL3Context->cellFsm, O5G_FSM_Print);

    for (nbLoop = 0; nbLoop < RAN_NODEB_NUM_MAX; nbLoop++)
    {
        pNbInst = &gpRanL3Context->nbInst[nbLoop];
        for (cellLoop = 0; cellLoop < RAN_CELL_NUM_MAX; cellLoop++)
        {
            pCellInst = &pNbInst->cellInst[cellLoop];
            snprintf(fsmInstId, sizeof(fsmInstId), "nb:%u,cell:%u", pCellInst->nbIdx, pCellInst->cellIdx);
            pCellInst->cellSmInst = FSM_INST_Init(gpRanL3Context->cellFsm, fsmInstId);
            IF_RETURN(==, NULL, pCellInst->cellSmInst, O5G_RC_ER, "RAN_L3_CELL_SM_Init() FSM_INST_Init() error!\n");
        }
    }

    gpRanL3Context->cellFsmEvtQue = FixRB_Create(NULL, 64, sizeof(S_FsmEventContext), FIX_RB_TYPE_NONE);
    IF_RETURN(==, NULL, gpRanL3Context->cellFsmEvtQue, O5G_RC_ER, "RAN_L3_CELL_SM_Init() FixRB_Create() error!\n");

    return O5G_RC_OK;
}

int32_t RAN_L3_CELL_SM_Final(void)
{
    uint32_t nbLoop;
    uint32_t cellLoop;
    S_RanL3NbInst *pNbInst;
    S_RanL3CellInst *pCellInst;

    for (nbLoop = 0; nbLoop < RAN_NODEB_NUM_MAX; nbLoop++)
    {
        pNbInst = &gpRanL3Context->nbInst[nbLoop];
        for (cellLoop = 0; cellLoop < RAN_CELL_NUM_MAX; cellLoop++)
        {
            pCellInst = &pNbInst->cellInst[cellLoop];
            FSM_INST_Final(pCellInst->cellSmInst);
        }
    }
    FSM_Final(gpRanL3Context->cellFsm);
    FixRB_Destroy(gpRanL3Context->cellFsmEvtQue);

    return O5G_RC_OK;
}

void RAN_L3_CELL_SM_ProcFsmEvent()
{
    int32_t rc;
    S_RanL3CellInst *pCellInst;
    uint32_t size;
    S_FsmEventContext evtCtxt;

    while (1)
    {
        size = sizeof(evtCtxt);
        rc = FixRB_Get(gpRanL3Context->cellFsmEvtQue, &evtCtxt, &size);
        IF_BREAK(!=, CSP_RC_OK, rc, NO_LOG_MESSAGE);

        pCellInst = (S_RanL3CellInst *)evtCtxt.context;
        FSM_INST_HandleEvent(pCellInst->cellSmInst, &evtCtxt);
    }
}

void RAN_L3_CELL_SM_IndProcess(S_OsSelectInd *pIndMsg)
{
    switch (pIndMsg->ind)
    {
    case RAN_L3_INTRA_IND_MSG_CELL_FSM_EVT:
        RAN_L3_CELL_SM_ProcFsmEvent();
        break;
    default:
        break;
    }
}

void RAN_L3_CELL_SM_MsgProcess(void)
{

}

void RAN_L3_CELL_SM_PrdProcess(void)
{

}
